package com.jia.utils;

import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * Created by fanfeipeng on 2015/6/18 0018.
 */
public class TimeUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(TimeUtils.class.getName());

    public static int getVirtualDays() {
        return virtualDays;
    }

    public static void setVirtualDays(int virtualDays) {
        TimeUtils.virtualDays = virtualDays;
    }

    /**
     * 一个虚拟时间差值,单位为天数
     */
    private static int virtualDays = 0;
    public static final SimpleDateFormat yyyyMMddFormat = new SimpleDateFormat("yyyyMMdd");
    public static final FastDateFormat yyyyMMdd = FastDateFormat.getInstance("yyyyMMdd");
    private static final FastDateFormat yyyyMM = FastDateFormat.getInstance("yyyyMM");
    private static final FastDateFormat mmdd = FastDateFormat.getInstance("MMdd");
    static final FastDateFormat fullSdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    static final FastDateFormat nianyuerisf = FastDateFormat.getInstance("yyyy年MM月dd日 HH:mm");
    static final FastDateFormat nianyueri = FastDateFormat.getInstance("yyyy年MM月dd日");
    private static final FastDateFormat dd = FastDateFormat.getInstance("dd");

    public static int getTodayId() {
        Date nowTime = getNowDate();
        return Integer.valueOf(yyyyMMdd.format(nowTime));
    }

    public static int getDayId(Date date) {
        return Integer.valueOf(yyyyMMdd.format(date));
    }

    public static int getCurrentMonthId() {
        Date nowTime = new Date();
        return Integer.valueOf(yyyyMM.format(nowTime));
    }

    public static int getYesterDayId() {
        return Integer.valueOf(yyyyMMdd.format(TimeUtils.getTruncatedYesterday()));
    }

    public static int getFullTagOfDay(Date date) {
        return Integer.valueOf(yyyyMMdd.format(date));
    }

    public static String getMMddTag() {
        return mmdd.format(getNowDate());
    }

    public static String getMMddTagOfDay(Date date) {
        return mmdd.format(date);
    }

    public static String getMMddTagOfYesterDay() {
        return mmdd.format(getTruncatedYesterday());
    }

    public static String getTodayDDTag() {
        return dd.format(new Date());
    }

    public static String getDDTagOfDay(Date date) {
        return dd.format(date);
    }

    public static String getYesterDayTag() {
        return dd.format(DateUtils.addDays(new Date(), -1));
    }

    public static String getNowStr() {
        return fullSdf.format(getNowDate());
    }

    public static Date getNowDate() {
//        if (DebugUtil.isDebug()) {
//            return DateUtils.addDays(new Date(), virtualDays);
//        }
        return new Date();
    }

    public static Calendar getVirtualCalendar() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getNowDate());
        return calendar;
    }

    /**
     * 前一个月最多多少天
     *
     * @return
     */
    public static int getPreviousMonthDayCount() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtils.addMonths(getNowDate(), -1));
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

//    /**
//     * 获取前一个月的天的logs
//     *
//     * @param days
//     * @return
//     */
//    public static String getPreviouseMonthDays(int days) {
//        String previousMonthDays = BinaryUtil.getZeroLeftPaddingBinaryString(days);
//        int previousMonthMaxDay = getPreviousMonthDayCount();
//        // 28 29 30
//        if (previousMonthMaxDay < BinaryUtil.BINARY_STR_LENGTH) {
//            previousMonthDays = previousMonthDays.substring(0, previousMonthMaxDay);
//        }
//        return previousMonthDays;
//    }

//    /**
//     * 要获取的是[本月1号-昨天]的连续登录日志,不包括今天和将来
//     *
//     * @param days
//     * @return
//     */
//    public static String getCurrentMonthDays(int days) {
//        Calendar calendar = Calendar.getInstance();
//        Date yesterDay = DateUtils.addDays(getNowDate(), -1);
//        // 昨天是前一个月,所以log为本月log暂时为空
//        if (yesterDay.before(DateUtils.truncate(getNowDate(), Calendar.MONTH))) {
//            return "";
//        }
//        calendar.setTime(yesterDay);
//        String daystr = BinaryUtil.getZeroLeftPaddingBinaryString(days);
//        int todayNumber = calendar.get(Calendar.DAY_OF_MONTH);
//        if (todayNumber < BinaryUtil.BINARY_STR_LENGTH) {
//            daystr = daystr.substring(0, todayNumber);
//        }
//        return daystr;
//    }

    public static final String formatToFull(Date date) {
        return null == date ? "" : fullSdf.format(date);
    }

    public static String formatToFullWithDefault(Date date, String defaultStr) {
        return null == date ? defaultStr : fullSdf.format(date);
    }

    /**
     * 通过尝试各种解析器解析日期字符串
     * 不允许February 942, 1996这种格式，否则抛ParseException
     *
     * @param time
     * @param defaultDate
     * @return
     */
    public static Date parseFromFullTimeStr(String time, Date defaultDate) {
        try {
            return DateUtils.parseDateStrictly(time, fullSdf.getPattern());
        } catch (Exception e) {
            LOGGER.error("parse time error:", e);
        }
        return defaultDate;
    }

    public static Date parseFromFullTimeStr(String time) {
        return parseFromFullTimeStr(time, null);
    }

    public static Date getTruncatedToday() {
        return getTruncatedDay(0);
    }

    public static Date getTruncatedYesterday() {
        return getTruncatedDay(-1);
    }

    public static Date getTruncatedTomorrow() {
        return getTruncatedDay(1);
    }


    public static Date getTruncatedSecondDay() {
        return getTruncatedDay(2);
    }

    /**
     * 当前时间增加或者减少指定天数，得到的日期
     *
     * @param offset
     * @return
     */
    public static Date getTruncatedDay(int offset) {
        return DateUtils.addDays(DateUtils.truncate(getNowDate(), Calendar.DAY_OF_MONTH), offset);
    }

    /**
     * 指定增加或者减少指定天数，得到的日期
     *
     * @param offset
     * @return
     */
    public static Date getSpecificDay(Date date, int offset) {
        return DateUtils.addDays(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), offset);
    }

    /**
     * 计算当前时间处于从开始时间开始的第几个时间段内
     * 正常情况下,开始时间可以是某天零点,时间间隔是1440分钟,则此功能就是计算当前时间是起点之后的第几天
     *
     * @param begin          开始时间
     * @param minuteInterval 间隔分钟
     * @return
     */
    public static long calcMinuteIndexFromBegin(Date begin, int minuteInterval) {
        return TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - begin.getTime()) / minuteInterval;
    }

    /**
     * 获取某个时刻的周一零点
     *
     * @param base
     * @return
     */
    public static Date getWeekMonday(Date base) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(base);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return DateUtils.truncate(calendar.getTime(), Calendar.DAY_OF_MONTH);
    }

    public static Date getThisWeekMonday() {
        return getWeekMonday(new Date());
    }

    public static Date getThisWeekSunday(Date date) {
        return DateUtils.addDays(getWeekMonday(date), 6);
    }

    /**
     * 获取下周一零点
     *
     * @return
     */
    public static Date getNextMonday() {
        return getMondayByWeeksOffset(new Date(), 1);
    }

    /**
     * 获取前后某周一零点,传入一个offset
     *
     * @param base
     * @return
     */
    public static Date getMondayByWeeksOffset(Date base, int weeks) {
        return DateUtils.addDays(getWeekMonday(base), 7 * weeks);
    }

    /**
     * 计算从begin开始，现在算是第几个自然日
     * 例如:上午8点充值，充值后在今天就算是第一天，过了零点就算是第二天
     * 一般情况，传进来的date，指的是玩家发生某个行为的时间点，或者是活动开始的时间点
     *
     * @param begin
     * @return
     */
    public static int calcNowDayIndexFromBegin(Date begin) {
        LocalDate date = begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return (int) ChronoUnit.DAYS.between(date, LocalDate.now()) + 1;
    }

    /**
     * 获得当月1号零点时间
     *
     * @return
     */
    public static Date getCurMonthBeginTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获得下月1号零点时间
     *
     * @return
     */
    public static Date getNextMonthBeginTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getCurMonthBeginTime());
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 获得上月1号零点时间
     *
     * @return
     */
    public static Date getLastMonthBeginTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getCurMonthBeginTime());
        calendar.add(Calendar.MONTH, -1);
        return calendar.getTime();
    }

    public static void main(String[] args) {
    /*    System.out.println(calcNowDayIndexFromBegin(DateUtils.addMinutes(new Date(), 1)));
        String date="2019-07-15 23:22:45";
        Date Time =parseFromFullTimeStr(date);
        System.out.println(DateUtils.addHours(Time, 1));
        System.out.println(getWeekMonday(new Date()));//
        System.out.println(DateUtils.addDays(getWeekMonday(new Date()),6));*/

        System.out.println("当月1号：");
        System.out.println(getCurMonthBeginTime().toString());
        System.out.println("下月1号：");
        System.out.println(getNextMonthBeginTime().toString());


    }

    /**
     * 判断当前时间距离第二天凌晨的差值
     */
    public static Long getTomorrow2Today() {
        Date now = getNowDate();
        Date tomorrow = getTruncatedTomorrow();
        return tomorrow.getTime() - now.getTime();
    }

    /**
     * 判断当前时间距离第三天凌晨的差值
     */
    public static Long getTomorrow3Today() {
        Date now = getNowDate();
        Date tomorrow = getTruncatedSecondDay();
        return tomorrow.getTime() - now.getTime();
    }

    /**
     * 判断当前时间距离下周一零点差值
     */
    public static Long getNextMonday2Today() {
        Date now = getNowDate();
        Date nextMonday = getNextMonday();
        return nextMonday.getTime() - now.getTime();
    }

    /**
     * 判断当前时间距离下月1号零点差值
     */
    public static Long getNextMonthBegin2Today() {
        Date now = getNowDate();
        Date nextMonday = getNextMonthBeginTime();
        return nextMonday.getTime() - now.getTime();
    }


    /**
     * 获取指定时长到期时间
     *
     * @return
     */
    public static Date getTargetCalendar(Date begin, Integer TimeLength) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(begin);
        calendar.add(calendar.DATE, TimeLength);
        return calendar.getTime();
    }

    /**
     * 获取时间长度，返回天数
     *
     * @return
     */
    public static Integer getTimeLength(Date beginTime, Date endTime, Integer appointTime) {
        Long time = endTime.getTime() - beginTime.getTime() / 1000 / 60 / 60 / 24;
        Integer allTime = time.intValue() + appointTime;//总时间
        return allTime;
    }

    /**
     * 获取时间长度,不加固定时长，返回天数
     *
     * @return
     */
    public static Integer getTimeLength2(Date beginTime, Date endTime) {
        Long time = endTime.getTime() - beginTime.getTime() / 1000 / 60 / 60 / 24;
        Integer allTime = time.intValue();//总时间
        return allTime;
    }

    public static String getChinaDateTime(Date date) {
        return nianyuerisf.format(date);
    }

    public static String getNowDateTime(Date date) {
        return nianyueri.format(date);
    }

    public static String getYMDTime(Date date) {
        return yyyyMMdd.format(date);
    }

    public static int getWeekOfYear() {
        Calendar calendar = Calendar.getInstance();

        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    public static int getChinaWeekOfYear() {
        Calendar calendar = Calendar.getInstance();
        if (calendar.get(Calendar.DAY_OF_WEEK) == 0) {
            Date date = DateUtils.addDays(calendar.getTime(), -1);
            calendar.setTime(date);
        }
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    public static int getUperWeekOfYear() {
        Calendar calendar = Calendar.getInstance();
        Date date = getTruncatedDay(-7);
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    //获取指定时间戳所在当天零点时间戳
    public static long getZeroClockStamp(long timeStamp) {
        Date date = new Date(timeStamp);
        Date zeroClock = DateUtils.truncate(date, Calendar.DATE);
        return zeroClock.getTime();
    }

    //获取当日零点时间戳
    public static long getTodayBeginTime() {
        return getZeroClockStamp(System.currentTimeMillis());
    }

    //获取当前时间 距离当日零点经过的秒数
    public static long getSecondsFromZero() {
        long curTime = System.currentTimeMillis();
        long zeroTime = getTodayBeginTime();
        long passSeconds = (curTime - zeroTime) / 1000;
        return passSeconds;
    }


    public static boolean isNowInlocalTime(List<Pair<LocalTime, LocalTime>> list) {
        boolean isFind = false;
        // 如果不配置表示全时间端内
        if (!list.isEmpty()) {
            LocalTime nowlocalTime = LocalTime.now();
            for (Pair<LocalTime, LocalTime> localTimes : list) {
                if (nowlocalTime.compareTo(localTimes.getLeft()) >= 0 && nowlocalTime.compareTo(localTimes.getRight()) <= 0) {
                    isFind = true;
                    break;
                }
            }
        }
        return isFind;
    }

    //算当天
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        Calendar cal = Calendar.getInstance();

        cal.setTime(smdate);

        long time1 = cal.getTimeInMillis();

        cal.setTime(bdate);

        long time2 = cal.getTimeInMillis();

        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }


    //不算当天
    public static int daysBetween(String smdate, String bdate) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar cal = Calendar.getInstance();

        cal.setTime(sdf.parse(smdate));

        long time1 = cal.getTimeInMillis();

        cal.setTime(sdf.parse(bdate));

        long time2 = cal.getTimeInMillis();

        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));

    }

    //给一个时间点   获得当前时间点到  第二天凌晨的时间差
    public static long getnextDay2nowDay(long dateTime) {
        SimpleDateFormat formata = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String getTime = formata.format(dateTime);//当时选择的时间
        Date date = null;
        try {
            date = DateUtils.parseDate(getTime, "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Date tomorrow = DateUtils.addDays(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), 1);
        long cha = 0;
        if (DateUtils.isSameDay(date, new Date())) {
            cha = tomorrow.getTime() - new Date().getTime();
        } else if (!DateUtils.isSameDay(date, new Date()) && new Date().after(date)) {
            cha = 0;
        }
        return cha;
    }


    /**
     * @param startTime 开始时间
     * @param days      有效期限 天
     * @return
     */
    public static long getExpirTime(String startTime, int days) {
        SimpleDateFormat formata = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        long lastTime = 0l;
        try {
            Date registerDate = sdf.parse(startTime);
            String getTime = formata.format(registerDate);
            Date date = DateUtils.parseDate(getTime, "yyyy-MM-dd HH:mm:ss");
            int expirTime = days * 1000 * 60 * 60 * 24;
            long result = date.getTime() + expirTime - new Date().getTime();
            if (result < 0) {
                lastTime = 0;
            } else {
                lastTime = result;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return lastTime;
    }
    //获取当天的开始时间
    public static Date getDayBegin() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }


    //获取当天的结束时间
    public static Date getDayEnd() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

}
